/**
 * IndexedDB存储适配器
 *
 * 实现StorageAdapter接口,使用IndexedDB作为存储后端
 * 注意: 接口升级为异步(返回Promise),这是合理的技术升级
 */

import { ContentType, type Content } from '../../../types/document'
import type {
  RecentContentEntry,
  ContentListItem,
  ContentQuery,
  StorageResult,
  StorageUsageSummary
} from '../types'
import { StorageErrorCode } from '../storageErrors'
import { AppDatabase } from './database'
import {
  StoredDocument,
  contentToStoredDocument,
  storedDocumentToContent
} from './types'

/**
 * IndexedDB适配器类
 */
export class IndexedDBAdapter {
  constructor(private db: AppDatabase) {}

  /**
   * 保存内容
   */
  async saveContent(content: Content): Promise<StorageResult<void>> {
    try {
      console.log('[IndexedDB适配器] 保存文档', content.id)

      // 转换为StoredDocument
      const doc = contentToStoredDocument(content)

      // 使用put方法,如果存在则更新,不存在则创建
      await this.db.documents.put(doc)

      console.log('[IndexedDB适配器] 文档已保存')
      return { ok: true, data: undefined }
    } catch (error) {
      console.error('[IndexedDB适配器] 保存失败', error)
      return {
        ok: false,
        error: {
          code: StorageErrorCode.UNKNOWN,
          message: '保存文档失败',
          cause: error
        }
      }
    }
  }

  /**
   * 根据ID获取内容
   */
  async getContentById(id: string): Promise<StorageResult<Content | null>> {
    try {
      console.log('[IndexedDB适配器] 获取文档', id)

      const doc = await this.db.documents.get(id)
      if (!doc) {
        console.log('[IndexedDB适配器] 文档不存在')
        return { ok: true, data: null }
      }

      // 转换回Content对象
      const content = storedDocumentToContent(doc)

      console.log('[IndexedDB适配器] 文档已获取')
      return { ok: true, data: content }
    } catch (error) {
      console.error('[IndexedDB适配器] 获取失败', error)
      return {
        ok: false,
        error: {
          code: StorageErrorCode.UNKNOWN,
          message: '获取文档失败',
          cause: error
        }
      }
    }
  }

  /**
   * 删除内容
   */
  async removeContent(id: string): Promise<StorageResult<void>> {
    try {
      console.log('[IndexedDB适配器] 删除文档', id)

      await this.db.documents.delete(id)

      console.log('[IndexedDB适配器] 文档已删除')
      return { ok: true, data: undefined }
    } catch (error) {
      console.error('[IndexedDB适配器] 删除失败', error)
      return {
        ok: false,
        error: {
          code: StorageErrorCode.UNKNOWN,
          message: '删除文档失败',
          cause: error
        }
      }
    }
  }

  /**
   * 获取最近文档列表
   */
  async listRecent(limit = 20): Promise<StorageResult<RecentContentEntry[]>> {
    try {
      console.log('[IndexedDB适配器] 获取最近文档', limit)

      // 使用_updatedAtTimestamp索引排序
      const docs = await this.db.documents
        .orderBy('_updatedAtTimestamp')
        .reverse() // 最新的在前
        .limit(limit)
        .toArray()

      const entries: RecentContentEntry[] = docs.map(doc => ({
        id: doc.id,
        title: doc.title,
        type: doc.type,
        savedAt: doc.updatedAt // 已经是ISO字符串
      }))

      console.log(`[IndexedDB适配器] 获取到${entries.length}个最近文档`)
      return { ok: true, data: entries }
    } catch (error) {
      console.error('[IndexedDB适配器] 获取最近文档失败', error)
      return {
        ok: false,
        error: {
          code: StorageErrorCode.UNKNOWN,
          message: '获取最近文档失败',
          cause: error
        }
      }
    }
  }

  /**
   * 获取内容列表(支持查询和排序)
   */
  async getContents(query?: ContentQuery): Promise<StorageResult<ContentListItem[]>> {
    try {
      console.log('[IndexedDB适配器] 获取内容列表', query)

      let collection = this.db.documents.toCollection()

      // 按类型筛选
      if (query?.type && query.type.length > 0) {
        collection = this.db.documents.where('type').anyOf(query.type)
      }

      // 排序
      const sortBy = query?.sortBy || 'updatedAt'
      const sortOrder = query?.sortOrder || 'desc'

      let docs: StoredDocument[]
      if (sortBy === 'updatedAt') {
        docs = await collection.sortBy('_updatedAtTimestamp')
      } else if (sortBy === 'createdAt') {
        // createdAt没有时间戳索引,需要手动排序
        docs = await collection.toArray()
        docs.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime())
      } else if (sortBy === 'title') {
        docs = await collection.sortBy('_searchTitle')
      } else {
        docs = await collection.toArray()
      }

      // 反转顺序(如果需要降序)
      if (sortOrder === 'desc') {
        docs.reverse()
      }

      // 限制数量
      if (query?.limit) {
        docs = docs.slice(0, query.limit)
      }

      // 转换为ContentListItem
      const items: ContentListItem[] = docs.map(doc => {
        const content = storedDocumentToContent(doc)

        // 计算字数(简单实现)
        let wordCount = 0
        if (content.type === ContentType.TEXT_DOCUMENT) {
          const data = content.data as any
          if (data.content) {
            wordCount = data.content.length
          }
        }

        // 生成预览(前100字符，去除HTML标签)
        let preview: string | undefined
        if (content.type === ContentType.TEXT_DOCUMENT) {
          const data = content.data as any
          if (data.content) {
            // 移除HTML标签，只保留纯文本
            const textContent = data.content
              .replace(/<[^>]*>/g, '') // 移除所有HTML标签
              .replace(/&nbsp;/g, ' ') // 替换&nbsp;为空格
              .replace(/&lt;/g, '<')   // HTML实体解码
              .replace(/&gt;/g, '>')
              .replace(/&amp;/g, '&')
              .replace(/&quot;/g, '"')
              .replace(/&#39;/g, "'")
              .replace(/\s+/g, ' ')    // 多个空格合并为一个
              .trim()                   // 去除首尾空白
            preview = textContent.substring(0, 100)
          }
        }

        return {
          id: content.id,
          title: content.title,
          type: content.type,
          status: content.status,
          createdAt: content.createdAt,
          updatedAt: content.updatedAt,
          wordCount,
          preview
        }
      })

      console.log(`[IndexedDB适配器] 获取到${items.length}个内容`)
      return { ok: true, data: items }
    } catch (error) {
      console.error('[IndexedDB适配器] 获取内容列表失败', error)
      return {
        ok: false,
        error: {
          code: StorageErrorCode.UNKNOWN,
          message: '获取内容列表失败',
          cause: error
        }
      }
    }
  }

  /**
   * 清空所有数据
   */
  async clear(): Promise<StorageResult<void>> {
    try {
      console.log('[IndexedDB适配器] 清空数据')

      await this.db.documents.clear()
      await this.db.versions.clear()
      await this.db.assets.clear()

      console.log('[IndexedDB适配器] 数据已清空')
      return { ok: true, data: undefined }
    } catch (error) {
      console.error('[IndexedDB适配器] 清空失败', error)
      return {
        ok: false,
        error: {
          code: StorageErrorCode.UNKNOWN,
          message: '清空数据失败',
          cause: error
        }
      }
    }
  }

  /**
   * 获取存储使用情况
   */
  async getNamespaceUsage(): Promise<StorageResult<StorageUsageSummary>> {
    try {
      console.log('[IndexedDB适配器] 获取存储使用情况')

      const itemCount = await this.db.documents.count()

      // IndexedDB不提供直接的字节数统计
      // 我们需要估算大小
      let usedBytes = 0
      const allDocs = await this.db.documents.toArray()
      for (const doc of allDocs) {
        // 粗略估算: JSON字符串的字节数
        const jsonStr = JSON.stringify(doc)
        usedBytes += jsonStr.length * 2 // UTF-16,每个字符2字节
      }

      console.log(`[IndexedDB适配器] 文档数: ${itemCount}, 估算大小: ${(usedBytes / 1024).toFixed(2)}KB`)
      return {
        ok: true,
        data: {
          itemCount,
          usedBytes
        }
      }
    } catch (error) {
      console.error('[IndexedDB适配器] 获取使用情况失败', error)
      return {
        ok: false,
        error: {
          code: StorageErrorCode.UNKNOWN,
          message: '获取存储使用情况失败',
          cause: error
        }
      }
    }
  }

  /**
   * 按标题搜索
   * 扩展方法(v1.0没有此方法)
   */
  async searchByTitle(keyword: string): Promise<StorageResult<Content[]>> {
    try {
      console.log('[IndexedDB适配器] 搜索标题', keyword)

      const lowerKeyword = keyword.toLowerCase()
      const docs = await this.db.documents
        .filter(doc => doc._searchTitle.includes(lowerKeyword))
        .toArray()

      const contents = docs.map(doc => storedDocumentToContent(doc))

      console.log(`[IndexedDB适配器] 找到${contents.length}个匹配文档`)
      return { ok: true, data: contents }
    } catch (error) {
      console.error('[IndexedDB适配器] 搜索失败', error)
      return {
        ok: false,
        error: {
          code: StorageErrorCode.UNKNOWN,
          message: '搜索失败',
          cause: error
        }
      }
    }
  }

  /**
   * 按类型筛选
   * 扩展方法(v1.0没有此方法)
   */
  async filterByType(type: ContentType): Promise<StorageResult<Content[]>> {
    try {
      console.log('[IndexedDB适配器] 按类型筛选', type)

      const docs = await this.db.documents
        .where('type')
        .equals(type)
        .toArray()

      const contents = docs.map(doc => storedDocumentToContent(doc))

      console.log(`[IndexedDB适配器] 找到${contents.length}个${type}文档`)
      return { ok: true, data: contents }
    } catch (error) {
      console.error('[IndexedDB适配器] 筛选失败', error)
      return {
        ok: false,
        error: {
          code: StorageErrorCode.UNKNOWN,
          message: '按类型筛选失败',
          cause: error
        }
      }
    }
  }

  /**
   * 批量保存
   * 扩展方法
   */
  async batchSave(contents: Content[]): Promise<StorageResult<void>> {
    try {
      console.log('[IndexedDB适配器] 批量保存', contents.length)

      const docs = contents.map(content => contentToStoredDocument(content))
      await this.db.documents.bulkPut(docs)

      console.log('[IndexedDB适配器] 批量保存完成')
      return { ok: true, data: undefined }
    } catch (error) {
      console.error('[IndexedDB适配器] 批量保存失败', error)
      return {
        ok: false,
        error: {
          code: StorageErrorCode.UNKNOWN,
          message: '批量保存失败',
          cause: error
        }
      }
    }
  }

  /**
   * 批量删除
   * 扩展方法
   */
  async batchRemove(ids: string[]): Promise<StorageResult<void>> {
    try {
      console.log('[IndexedDB适配器] 批量删除', ids.length)

      await this.db.documents.bulkDelete(ids)

      console.log('[IndexedDB适配器] 批量删除完成')
      return { ok: true, data: undefined }
    } catch (error) {
      console.error('[IndexedDB适配器] 批量删除失败', error)
      return {
        ok: false,
        error: {
          code: StorageErrorCode.UNKNOWN,
          message: '批量删除失败',
          cause: error
        }
      }
    }
  }

  // ========== 版本管理方法 ==========

  /**
   * 保存文档版本
   * @param documentId 文档ID
   * @param content 版本内容
   * @param comment 版本备注
   * @returns 版本ID
   */
  async saveVersion(
    documentId: string,
    content: string,
    comment?: string
  ): Promise<StorageResult<string>> {
    try {
      console.log('[IndexedDB适配器] 保存版本', documentId)

      const versionId = `${documentId}_${Date.now()}`
      const version = {
        id: versionId,
        documentId,
        content,
        diff: '', // TODO: 实现增量差异计算
        createdAt: Date.now(),
        createdBy: 'local', // TODO: 支持多用户
        comment: comment || '自动保存',
        tag: ''
      }

      await this.db.versions.add(version)

      console.log('[IndexedDB适配器] 版本已保存', versionId)
      return { ok: true, data: versionId }
    } catch (error) {
      console.error('[IndexedDB适配器] 保存版本失败', error)
      return {
        ok: false,
        error: {
          code: StorageErrorCode.UNKNOWN,
          message: '保存版本失败',
          cause: error
        }
      }
    }
  }

  /**
   * 获取文档的所有版本
   * @param documentId 文档ID
   * @returns 版本列表(按时间倒序)
   */
  async getVersions(documentId: string): Promise<StorageResult<any[]>> {
    try {
      console.log('[IndexedDB适配器] 获取版本列表', documentId)

      const versions = await this.db.versions
        .where('documentId')
        .equals(documentId)
        .reverse()
        .sortBy('createdAt')

      console.log(`[IndexedDB适配器] 找到${versions.length}个版本`)
      return { ok: true, data: versions }
    } catch (error) {
      console.error('[IndexedDB适配器] 获取版本列表失败', error)
      return {
        ok: false,
        error: {
          code: StorageErrorCode.UNKNOWN,
          message: '获取版本列表失败',
          cause: error
        }
      }
    }
  }

  /**
   * 根据版本ID获取版本内容
   * @param versionId 版本ID
   * @returns 版本内容
   */
  async getVersionById(versionId: string): Promise<StorageResult<any | null>> {
    try {
      console.log('[IndexedDB适配器] 获取版本', versionId)

      const version = await this.db.versions.get(versionId)
      if (!version) {
        console.log('[IndexedDB适配器] 版本不存在')
        return { ok: true, data: null }
      }

      console.log('[IndexedDB适配器] 版本已获取')
      return { ok: true, data: version }
    } catch (error) {
      console.error('[IndexedDB适配器] 获取版本失败', error)
      return {
        ok: false,
        error: {
          code: StorageErrorCode.UNKNOWN,
          message: '获取版本失败',
          cause: error
        }
      }
    }
  }

  /**
   * 删除文档的所有版本
   * @param documentId 文档ID
   */
  async deleteVersions(documentId: string): Promise<StorageResult<void>> {
    try {
      console.log('[IndexedDB适配器] 删除文档版本', documentId)

      await this.db.versions
        .where('documentId')
        .equals(documentId)
        .delete()

      console.log('[IndexedDB适配器] 版本已删除')
      return { ok: true, data: undefined }
    } catch (error) {
      console.error('[IndexedDB适配器] 删除版本失败', error)
      return {
        ok: false,
        error: {
          code: StorageErrorCode.UNKNOWN,
          message: '删除版本失败',
          cause: error
        }
      }
    }
  }

  /**
   * 恢复到指定版本
   * @param documentId 文档ID
   * @param versionId 版本ID
   * @returns 更新后的文档
   */
  async restoreVersion(documentId: string, versionId: string): Promise<StorageResult<Content>> {
    try {
      console.log('[IndexedDB适配器] 恢复版本', documentId, versionId)

      // 获取版本内容
      const versionResult = await this.getVersionById(versionId)
      if (!versionResult.ok || !versionResult.data) {
        return {
          ok: false,
          error: {
            code: StorageErrorCode.UNKNOWN,
            message: '版本不存在'
          }
        }
      }

      // 获取当前文档
      const docResult = await this.getContentById(documentId)
      if (!docResult.ok || !docResult.data) {
        return {
          ok: false,
          error: {
            code: StorageErrorCode.UNKNOWN,
            message: '文档不存在'
          }
        }
      }

      // 更新文档内容
      const doc = docResult.data
      if (doc.type === ContentType.TEXT_DOCUMENT) {
        const data = doc.data as any
        data.content = versionResult.data.content
      }
      doc.updatedAt = new Date()

      // 保存更新后的文档
      await this.saveContent(doc)

      console.log('[IndexedDB适配器] 版本已恢复')
      return { ok: true, data: doc }
    } catch (error) {
      console.error('[IndexedDB适配器] 恢复版本失败', error)
      return {
        ok: false,
        error: {
          code: StorageErrorCode.UNKNOWN,
          message: '恢复版本失败',
          cause: error
        }
      }
    }
  }
}
